package com.go.where.family.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.cookie.Cookie;
import org.apache.http.cookie.CookieOrigin;
import org.apache.http.cookie.CookieSpec;
import org.apache.http.cookie.CookieSpecFactory;
import org.apache.http.cookie.MalformedCookieException;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BrowserCompatSpec;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

public class HttpClientSpecial {

	/**
	 * 默认编码
	 */
	private String DEFAULTENCODE = "UTF-8";

	/**
	 * post请求方式
	 * 
	 * @param address
	 *            访问地址
	 * @param encode
	 *            编码方式
	 * @param params
	 *            参数
	 * @return 返回字符串内容
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public String doPost(String address, String encode,
			List<NameValuePair> params) throws ClientProtocolException,
			IOException {
		DefaultHttpClient httpClient = new DefaultHttpClient();

		HttpPost post = new HttpPost(address);

		post.setEntity(new UrlEncodedFormEntity(params, encode));

		HttpResponse response = httpClient.execute(post);

		HttpEntity entity = response.getEntity();

		String content = EntityUtils.toString(entity);

		return content;
	}

	/**
	 * post提交，pars为提交的参数
	 * 
	 * @param url
	 *            地址
	 * @param pars
	 *            参数
	 * @param encoding
	 *            指定编码
	 * @return 响应方响应的页面
	 * @throws Exception
	 */
	public String doPost(String url, Map<String, String> pars, String encoding)
			throws Exception {
		DefaultHttpClient httpclient = new DefaultHttpClient();
		httpclient.getParams().setParameter(
				CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
		httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
				10000);
		HttpPost httpPost = new HttpPost(url);
		httpPost.setHeader("User-Agent",
				"Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0");
		httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
		try {
			List<NameValuePair> nvps = null;
			if (pars != null && !pars.isEmpty()) {
				nvps = new ArrayList<NameValuePair>();
				Iterator<Entry<String, String>> it = pars.entrySet().iterator();
				while (it.hasNext()) {
					Entry<String, String> entry = it.next();
					nvps.add(new BasicNameValuePair(entry.getKey(), entry
							.getValue()));
				}
				UrlEncodedFormEntity encodeform = new UrlEncodedFormEntity(
						nvps, Charset.forName(encoding));
				httpPost.setEntity(encodeform);
			}
			HttpResponse httpresponse = httpclient.execute(httpPost);
			if (httpresponse.getStatusLine().getStatusCode() == 200) {
				InputStream stream = httpresponse.getEntity().getContent();
				HttpEntity httpEntity = httpresponse.getEntity();
				Header header = httpEntity.getContentEncoding();
				String encode = null;
				if (header != null) {
					encode = header.getName();
				}
				if (encode == null) {
					encode = encoding;
				}
				StringBuilder sb = new StringBuilder();
				InputStreamReader inReader = new InputStreamReader(stream,
						encode);
				BufferedReader reader = new BufferedReader(inReader);
				String rdline = null;
				while ((rdline = reader.readLine()) != null) {
					sb.append(rdline).append("\n");
				}
				reader.close();
				return sb.toString().trim();
			} else {
				throw new HttpException("返回信息不正确，返回状态码："
						+ httpresponse.getStatusLine().getStatusCode());
			}
		} finally {
			httpPost.releaseConnection();
		}
	}

	/**
	 * https post请求
	 * 
	 * @param url
	 * @param pars
	 * @param encoding
	 * @return
	 * @throws Exception
	 */
	public String doHttpsPost(String url, Map<String, String> pars,
			String encoding) throws Exception {
		DefaultHttpClient httpclient = new DefaultHttpClient();
		httpclient.getParams().setParameter(
				CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);
		httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
				10000);

		X509TrustManager xtm = new X509TrustManager() { // 创建TrustManager
			@Override
			public void checkClientTrusted(X509Certificate[] arg0, String arg1)
					throws java.security.cert.CertificateException {
			}

			@Override
			public void checkServerTrusted(X509Certificate[] arg0, String arg1)
					throws java.security.cert.CertificateException {
			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};

		CookieSpecFactory csf = new CookieSpecFactory() {
			public CookieSpec newInstance(HttpParams params) {
				return new BrowserCompatSpec() {
					@Override
					public void validate(Cookie cookie, CookieOrigin origin)
							throws MalformedCookieException {
						// Oh, I am easy
					}
				};
			}
		};

		httpclient.getCookieSpecs().register("easy", csf);
		httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY, "easy");

		// TLS1.0与SSL3.0基本上没有太大的差别，可粗略理解为TLS是SSL的继承者，但它们使用的是相同的SSLContext
		SSLContext ctx = SSLContext.getInstance("TLS");

		// 使用TrustManager来初始化该上下文，TrustManager只是被SSL的Socket所使用
		ctx.init(null, new TrustManager[] { xtm }, null);

		// 创建SSLSocketFactory
		SSLSocketFactory socketFactory = new SSLSocketFactory(ctx,
				SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

		// 通过SchemeRegistry将SSLSocketFactory注册到我们的HttpClient上
		httpclient.getConnectionManager().getSchemeRegistry()
				.register(new Scheme("https", 443, socketFactory));

		HttpPost httpPost = new HttpPost(url);
		httpPost.setHeader("User-Agent",
				"Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0");
		httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
		try {
			List<NameValuePair> nvps = null;
			if (pars != null && !pars.isEmpty()) {
				nvps = new ArrayList<NameValuePair>();
				Iterator<Entry<String, String>> it = pars.entrySet().iterator();
				while (it.hasNext()) {
					Entry<String, String> entry = it.next();
					nvps.add(new BasicNameValuePair(entry.getKey(), entry
							.getValue()));
				}
				UrlEncodedFormEntity encodeform = new UrlEncodedFormEntity(
						nvps, Charset.forName(encoding));
				httpPost.setEntity(encodeform);
			}
			HttpResponse httpresponse = httpclient.execute(httpPost);
			if (httpresponse.getStatusLine().getStatusCode() == 200) {
				InputStream stream = httpresponse.getEntity().getContent();
				HttpEntity httpEntity = httpresponse.getEntity();
				Header header = httpEntity.getContentEncoding();
				String encode = null;
				if (header != null) {
					encode = header.getName();
				}
				if (encode == null) {
					encode = encoding;
				}
				StringBuilder sb = new StringBuilder();
				InputStreamReader inReader = new InputStreamReader(stream,
						encode);
				BufferedReader reader = new BufferedReader(inReader);
				String rdline = null;
				while ((rdline = reader.readLine()) != null) {
					sb.append(rdline).append("\n");
				}
				reader.close();
				return sb.toString().trim();
			} else {
				throw new HttpException("返回信息不正确，返回状态码："
						+ httpresponse.getStatusLine().getStatusCode());
			}
		} finally {
			httpPost.releaseConnection();
		}
	}

	/**
	 * https get方式提交
	 * 
	 * @param url
	 * @param supplyEncode
	 *            供应商返回消息编码方式
	 * @return
	 * @throws Exception
	 */
	public String doHttpsGet(String url, String encode) throws Exception {
		DefaultHttpClient httpclient = new DefaultHttpClient();
		httpclient.getParams().setParameter(
				CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);
		httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
				10000);

		X509TrustManager xtm = new X509TrustManager() { // 创建TrustManager
			@Override
			public void checkClientTrusted(X509Certificate[] arg0, String arg1)
					throws java.security.cert.CertificateException {
			}

			@Override
			public void checkServerTrusted(X509Certificate[] arg0, String arg1)
					throws java.security.cert.CertificateException {
			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};

		CookieSpecFactory csf = new CookieSpecFactory() {
			public CookieSpec newInstance(HttpParams params) {
				return new BrowserCompatSpec() {
					@Override
					public void validate(Cookie cookie, CookieOrigin origin)
							throws MalformedCookieException {
						// Oh, I am easy
					}
				};
			}
		};

		httpclient.getCookieSpecs().register("easy", csf);
		httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY, "easy");

		// TLS1.0与SSL3.0基本上没有太大的差别，可粗略理解为TLS是SSL的继承者，但它们使用的是相同的SSLContext
		SSLContext ctx = SSLContext.getInstance("TLS");

		// 使用TrustManager来初始化该上下文，TrustManager只是被SSL的Socket所使用
		ctx.init(null, new TrustManager[] { xtm }, null);

		// 创建SSLSocketFactory
		SSLSocketFactory socketFactory = new SSLSocketFactory(ctx);

		// 通过SchemeRegistry将SSLSocketFactory注册到我们的HttpClient上
		httpclient.getConnectionManager().getSchemeRegistry()
				.register(new Scheme("https", 443, socketFactory));

		HttpGet httpGet = new HttpGet(url);
		httpGet.setHeader("User-Agent",
				"Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0");
		httpGet.setHeader("X-Requested-With", "XMLHttpRequest");
		HttpResponse httpresponse = httpclient.execute(httpGet);
		try {
			if (httpresponse.getStatusLine().getStatusCode() == 200) {
				InputStream stream = httpresponse.getEntity().getContent();
				HttpEntity httpEntity = httpresponse.getEntity();
				Header header = httpEntity.getContentEncoding();
				if (header != null) {
					encode = header.getName();
				}
				if (encode == null) {
					try {
						Charset cs = Charset.forName(encode);
						encode = cs.name();
					} catch (Exception e) {
					}
				}
				if (encode == null) {
					encode = DEFAULTENCODE;
				}
				StringBuilder sb = new StringBuilder();
				InputStreamReader inReader = new InputStreamReader(stream,
						encode);
				BufferedReader reader = new BufferedReader(inReader);
				String rdline = null;
				String str = null;
				while ((str = reader.readLine()) != null) {
					rdline = str;
					sb.append(rdline).append("\n");
				}

				reader.close();
				return sb.toString().trim();
			} else {
				throw new HttpException("返回信息不正确，返回状态码："
						+ httpresponse.getStatusLine().getStatusCode());
			}
		} finally {
			httpGet.releaseConnection();
		}
	}
	private final static int CONNECT_TIMEOUT = 5000; // in milliseconds
    private final static String DEFAULT_ENCODING = "UTF-8";
     
    public String postData(String urlStr, String data){
        return postData(urlStr, data, null);
    }
     
    public String postData(String urlStr, String data, String contentType) {
        BufferedReader reader = null;
        try {
            URL url = new URL(urlStr);
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            conn.setConnectTimeout(CONNECT_TIMEOUT);
            conn.setReadTimeout(CONNECT_TIMEOUT);
            if(StringUtils.isNotBlank(contentType))
                conn.setRequestProperty("content-type", contentType);
            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
            if(data == null)
                data = "";
            writer.write(data); 
            writer.flush();
            writer.close();  
 
            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
                sb.append("\r\n");
            }
            return sb.toString();
        } catch (IOException e) {
        	e.printStackTrace();
        } finally {
            try {
                if (reader != null)
                    reader.close();
            } catch (IOException e) {
            }
        }
        return null;
    }

}
